const xl = require("xlsx");
const fs = require("fs");
const path = require("path");

/**
 * 分析配置表
 * @param excel 表名
 * @param excelFen 表名 +分表名
 * @param excelAndSheets 表格与表单的数据类型 example:{iconopen:{id:string}}
 * @param clientOrServerRow 3=客户端，4=服务端
 * @param excelDir excel 放置目录
 * @param outDir 输出目录
 */
function doExcel(excel, excelFen, excelAndSheets, clientOrServerRow, excelDir, outDir) {
    let fileDir = path.join(excelDir, excel)
    let workbook = xl.readFile(fileDir);
    // 获取 Excel 中所有表名
    const sheetNames = workbook.SheetNames; // 返回 ['sheet1', 'sheet2']
    let _sheetNames = [];
    sheetNames.forEach((element) => {
        if (element.charAt(0) !== '!') {
            _sheetNames.push(element);
        }
    });
    if (_sheetNames.length === 0) {
        return;
    }
    console.log('start parsing excel', excel)
    const excelName = excel.split('_')[0]
    // 加到【excelAndSheets】中
    let obj = {};
    excelAndSheets[excelName] = {};
    _sheetNames.forEach((sheetName) => {
        let sheet = workbook.Sheets[sheetName];
        excelAndSheets[excelName][sheetName] = {};
        doSheet(obj, excelName, sheetName, sheet, clientOrServerRow, excelFen, excelAndSheets);
    });

    if (!fs.existsSync(outDir)) {
        fs.mkdirSync(outDir, {recursive: true})
    }
    for (const key in obj) {
        let jsonStr = `${geShiHua(obj[key])}`;
        fs.writeFileSync(path.join(outDir, `${key}.json`), jsonStr, 'utf-8')
    }
}

// 格式化数据
function geShiHua(data) {
    let count = 1;
    let _data = '[\n';
    for (const val of data) {
        if (count === 1) {
            _data += '  ' + JSON.stringify(val);
        } else {
            _data += `,\n`;
            _data += '  ' + JSON.stringify(val);
        }
        count++;
    }
    _data += '\n]';
    return _data;
}

//分析表单  obj数据，表名，表单名，表单数据内容
function doSheet(obj, excelName, sheetName, sheet, clientOrServerRow, excelFen, excelAndSheets) {
    let newKey = excelName + toUpperCaseByStr(sheetName);
    excelFen.push(newKey);
    if (obj[newKey] == null) {
        obj[newKey] = [];
    }

    // 索引列表  example:{A:"",B:"id",C:"hp",D:"attack"}
    let keyList = {};
    // 类型列表 example:{A:"number",B:"string",C:"boolean",D:"{}[]"}
    let typeList = {};
    //备注
    let psList = {};

    let _tempObj = {};
    for (const key in sheet) {
        // 单元格定位id example: A25
        const sheetKey = sheet[key];
        // A25->25
        let _hang = key.replace(/[^0-9]+/gi, '');
        // A25->A
        let _lie = key.replace(/[^A-Z]+/gi, '');
        if (_lie === 'A') {
            if (Object.keys(_tempObj).length > 0) {
                //这边检测是否有放空配置的。如果有 ， 补上默认类型
                let _tempObj_1 = {};
                for (const key in keyList) {
                    if (_tempObj[keyList[key]] == null) {
                        if (typeList[key] === 'number') {
                            _tempObj_1[keyList[key]] = 0;
                        } else if (typeList[key] === 'string') {
                            _tempObj_1[keyList[key]] = '';
                        } else if (typeList[key] === 'boolean') {
                            _tempObj_1[keyList[key]] = false;
                        } else if (typeList[key].indexOf('[]') !== -1) {
                            // 列表默认为空数组
                            _tempObj_1[keyList[key]] = [];
                        } else if (typeList[key].substring(0, 1) === '{') {
                            _tempObj_1[keyList[key]] = null;
                        } else if (typeList[key][0] === "[" && typeList[key][typeList[key].length - 1] === "]") { // 元组
                            _tempObj_1[keyList[key]] = null;
                        } else {
                            console.error('配置表有未知定义', excelName, sheetName, keyList[key], typeList[key]);
                        }
                    } else {
                        _tempObj_1[keyList[key]] = _tempObj[keyList[key]];
                    }
                }

                obj[newKey].push(_tempObj_1);
                _tempObj = {};
            }
        }
        if (sheet['A' + _hang] == null) {
            // 第一列没有配置参数,就跳过
            continue;
        }
        // 第一行，字段说明
        if (_hang == 1) {
            psList[_lie] = sheetKey.v;
        }
        // 储存类型
        if (_hang == 2) {
            typeList[_lie] = sheetKey.v;
        }
        // 储存索引
        if (_hang == clientOrServerRow && sheetKey.v && typeList[_lie]) {
            // 正则抽取真正的值(去掉所有的*)
            let realVal = sheetKey.v.replace(/[\*]/g, '');
            // 判断下作为key的字段
            let isKey = 0; // 0:不是key，1:单key，2:列表key
            if (sheetKey.v.slice(0, 2) === '**') {
                isKey = 2;
            } else if (sheetKey.v.slice(0, 1) === '*') {
                isKey = 1;
            }
            keyList[_lie] = realVal.split(',')[0].trim();
            // id:string
            excelAndSheets[excelName][sheetName][keyList[_lie]] = {
                ps: psList[_lie],
                isKey: isKey,
                value: typeList[_lie],
                keys: realVal
            };
        }
        // 储存数据
        if (_hang >= 5 && keyList[_lie] != null && typeList[_lie] != null) {
            // 根据类型转化数据内容,在做储存处理
            let _val;
            if (typeList[_lie] === 'number') {
                if (typeof sheetKey.v !== 'number') {
                    _val = Number(sheetKey.v);
                    if (isNaN(_val)) {
                        console.log(
                            '\x1b[33m%s\x1b[0m',
                            '警告,出现NaN数据类型,表名:' +
                            excelName +
                            ' 表单:' +
                            sheetName +
                            ' 索引:' +
                            keyList[_lie] +
                            ' 表格ID:' +
                            key
                        );
                    }
                    _val = 0;
                } else {
                    _val = sheetKey.v;
                }
            } else if (typeList[_lie] === 'boolean') {
                if (sheetKey.v === 'true' || sheetKey.v === 'TRUE' || sheetKey.v === true) {
                    _val = true;
                } else {
                    _val = false;
                }
            } else if (typeList[_lie][0] === '{' || typeList[_lie].slice(-1) === ']') {
                try {
                    _val = JSON.parse(sheetKey.v);
                } catch (error) {
                    console.log(
                        '\x1b[33m%s\x1b[0m',
                        '警告:json格式错误,表名:' + excelName + ' 表单:' + sheetName + ' 索引:' + keyList[_lie] + ' 表格ID:' + key
                    );
                }
            } else if (typeList[_lie] === 'string') {
                if (typeof sheetKey.v == 'number') {
                    // 数字型，字符串，防止出现小数
                    _val = parseInt(sheetKey.v).toString()
                } else {
                    _val = sheetKey.v;
                }
            } else {
                _val = sheetKey.v;
            }

            _tempObj[keyList[_lie].trim()] = _val;
        }
    }

    //这边检测是否有放空配置的。如果有 ， 补上默认类型
    let _tempObj_1 = {};
    for (const key in keyList) {
        if (_tempObj[keyList[key]] == null) {
            if (typeList[key] === 'number') {
                _tempObj_1[keyList[key]] = 0;
            } else if (typeList[key] === 'string') {
                _tempObj_1[keyList[key]] = '';
            } else if (typeList[key] === 'boolean') {
                _tempObj_1[keyList[key]] = false;
            } else if (typeList[key].indexOf('[]') !== -1) {
                _tempObj_1[keyList[key]] = [];
            } else if (typeList[key].substring(0, 1) === '{') {
                _tempObj_1[keyList[key]] = null;
            } else if (typeList[key][0] === "[" && typeList[key][typeList[key].length - 1] === "]") { // 元组
                _tempObj_1[keyList[key]] = null;
            } else {
                console.error('配置表有未知定义', excelName, sheetName, keyList[key], typeList[key]);
            }
        } else {
            _tempObj_1[keyList[key]] = _tempObj[keyList[key]];
        }
    }

    // 储存最后一个
    obj[newKey].push(_tempObj_1);
}

// 字符串开头变为大写
function toUpperCaseByStr(name) {
    return name.charAt(0).toUpperCase() + name.slice(1)
}


module.exports = {
    doExcel,
    toUpperCaseByStr,
}
